home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
parallax
/
more_exa.tar
/
more
/
Music
/
fractal_music.p
next >
Wrap
Text File
|
1993-03-05
|
4KB
|
129 lines
SYSTEM fractal_music;
(* This program generates fractal music. Its output is saved in MIDI file *)
(* format, which can be played on a synthesizer with a sequencer *)
(* Thomas Braunl, Univ. Stuttgart, 1993 *)
CONST maxlevel = 5;
low_val = 0.0;
high_val = 1.0;
maxnode = 2**maxlevel - 1;
TYPE list = ARRAY [1..maxnode] OF REAL;
(* specification of binary tree-structure *)
CONFIGURATION tree [1..maxnode];
CONNECTION child_l : tree[i] <-> tree[2*i].parent;
child_r : tree[i] <-> tree[2*i+1].parent;
SCALAR i,j : INTEGER;
delta : REAL;
field : list;
VECTOR x, low, high: REAL;
PROCEDURE Gauss(): VECTOR REAL;
(* random number with Gaussian distribution *)
CONST N = 4;
GA= SQRT(3.0*FLOAT(N));
GF= 2.0*GA / (FLOAT(N)*FLOAT(MAX(INTEGER)));
SCALAR i : INTEGER;
VECTOR sum: REAL;
BEGIN
sum:=0.0;
FOR i:=1 TO N DO sum:= sum + FLOAT(VIRandom()) END;
RETURN (GF*sum - GA)
END Gauss;
PROCEDURE MidPointRec(SCALAR delta: REAL; SCALAR level: INTEGER);
BEGIN
PARALLEL [2**(level-1) .. 2**level - 1] (* select current tree level *)
x := 0.5 * (low + high) + delta*Gauss();
IF level < maxlevel THEN
SEND tree.child_l (low) TO tree.parent(low); (* values for children *)
SEND tree.child_l (x) TO tree.parent(high);
SEND tree.child_r (x) TO tree.parent(low);
SEND tree.child_r (high) TO tree.parent(high);
END;
ENDPARALLEL;
END MidPointRec;
PROCEDURE WriteMidiFile(SCALAR f: list);
CONST text = "Parallaxis Music - Braunl, Univ. Stuttgart '93";
textlen = 46;
bottom = 60; (* MIDI no. of note C3 *)
range = 12.0; (* one octave *)
forte = 96; (* key pressure *)
mezzoforte = 64; (* key pressure *)
piano = 32; (* key pressure *)
TYPE string = ARRAY[1..30] OF CHAR;
PROCEDURE WriteLen(SCALAR l: INTEGER);
SCALAR l2,l3,l4: INTEGER;
BEGIN (* write argument as 4 bytes *)
l4 := l MOD 256; l := l DIV 256;
l3 := l MOD 256; l := l DIV 256;
l2 := l MOD 256; l := l DIV 256; (* now l only has its most sig. byte *)
Write(CHR(l)); Write(CHR(l2)); Write(CHR(l3)); Write(CHR(l4));
END WriteLen;
PROCEDURE WriteHex(SCALAR s: string);
SCALAR i,hex: INTEGER;
BEGIN (* interpret argument as hex string *)
i:=1;
WHILE s[i] # CHR(0) DO
IF s[i] <= '9' THEN hex := 16 * (ORD(s[i]) - ORD('0'))
ELSE hex := 16 * (ORD(s[i]) - ORD('A') + 10)
END;
IF s[i+1] <= '9' THEN inc(hex, ORD(s[i+1]) - ORD('0'))
ELSE inc(hex, ORD(s[i+1]) - ORD('A') + 10)
END;
Write(CHR(hex));
inc(i,2);
WHILE s[i] = ' ' DO inc(i,1) END; (* skip blanks *)
END
END WriteHex;
PROCEDURE inorder(SCALAR node: INTEGER);
SCALAR note: INTEGER;
BEGIN
IF node <= maxnode THEN
inorder(2*node);
note := bottom + TRUNC(range*field[node]);
WriteHex("00 90"); Write(CHR(note)); Write(CHR(mezzoforte)); (* note on *)
WriteHex("60 80"); Write(CHR(note)); Write(CHR(mezzoforte)); (* note off*)
inorder(2*node+1); (* duration 60 = 1/4 note *)
END
END inorder;
BEGIN
OpenOutput("fractal.midi");
WriteString("MThd"); (* header and fixed length *)
WriteLen(6);
WriteHex("00 00 00 01 00 60"); (* format 0, track 1, div.for 1/4 note *)
WriteString("MTrk"); (* track and calculated length *)
WriteLen(maxnode*8 +3 +textlen +18 +4);
WriteHex("00 FF 01"); (* text *)
Write(CHR(textlen)); (* text length *)
WriteString(text);
WriteHex("00 FF 58 04 04 02 18 08"); (* time signature *)
WriteHex("00 FF 51 03 07 A1 20"); (* tempo *)
WriteHex("00 C0 01"); (* track 1 (no. 0) on program/sound 1 *)
inorder(1); (* print all array elements as notes *)
WriteHex("00 FF 2F 00"); (* end of track *)
CloseOutput;
END WriteMidiFile;
BEGIN (* main *)
PARALLEL
low := low_val; (* starting values *)
high := high_val;
x := 0.0;
ENDPARALLEL;
FOR i:=1 TO maxlevel DO
delta := 0.5 ** (FLOAT(i)/2.0);
MidPointRec(delta,i);
END;
STORE(x,field);
WriteMidiFile(field);
END fractal_music.